import $U from "./util.js"
import $R from "@/common/free-lib/request.js"
import $store from "@/store/index.js"
class chat {
	constructor(arg) {
		this.url = arg.url
		//判断用户是否在线
		this.isOnline = false
		
		this.reconnectTime = 0
		this.isConnect = false
		//获得socketTask
		this.socket = null
		//当前用户id(获取token)
		let user = $U.getStorage('user')
		this.user = user ? JSON.parse(user) : {
			id: 0
		},
		this.bgAudioMannager = uni.getBackgroundAudioManager();
		this.platform = uni.getSystemInfoSync().platform;
		this.isCurrentChat = false
		//初始化聊天对象
		this.To = false
		//连接和监听
		if (this.user.token) {
			this.connectSocket()
		}
	}

	//连接socket
	connectSocket() {
		 
		//连接websocket
		this.socket = uni.connectSocket({
			url: this.url + "?token=" + this.user.token,
			complete: () => {}
		})

		//监听是否连接成功
		this.socket.onOpen(() => {
			this.onOpen()
		})
		//监听断开
		this.socket.onError(() => {
			this.onError()
		})
		//监听关闭
		this.socket.onClose(() => {
			this.onClose()
		})
		//监听消息
		this.socket.onMessage((res) => {
			this.onMessage(res)
		})
	}

	//监听打开
	onOpen() {
		//用户上线
		this.isOnline = true
		// console.log('连接成功')
		this.isConnect = true
		//获取离线消息
		$R.get('/chat/getOfflineMes').then(data=>{
			
			if(data.length>0){
				data.forEach(v=>{
					this.handleOnMessage(v.message)
				})
			}
		})
	}
	//监听关闭
	onClose() {
		//用户下线
		this.isOnline = false
		this.reconnect()
		
		// console.log('关闭')
		
	}
	//监听错误
	onError() {
		this.isOnline = false
		this.reconnect()
		// console.log('错误')
		
	}
	//关闭连接
	close() {
		 // console.log(this.socket)
		if(this.socket!==null){
			this.socket.close()
		}
		this.isConnect = false
		// console.log('离线')
	}
	//监听消息
	onMessage(res) {
		
		let data = JSON.parse(res.data)
		
		switch(data.msg){
			//对方被拉黑或被禁用，后端直接抛异常
			case 'fail':
				uni.showToast({
					title: res.data,
					icon: 'none'
				});
				break;
			//接收撤回消息
			case 'recall':
				this.handleOnRecall(data.data)
				break;
			case 'updateApplyList':
			
				$store.dispatch('getApply')
				this.bgAudioMannager.src = '/static/moment.mp3'; 
				this.messageNotice()
				break;
			//朋友圈相关
			case 'moment':
				this.bgAudioMannager.src = '/static/moment.mp3';
				
				this.handleMoment(data.data)
				break;
			default:
			this.bgAudioMannager.src = '/static/notice3.mp3';
			this.handleOnMessage(data.data)
		}


	}
	
	//断线重连
	reconnectConfirm() {
		this.reconnectTime = 0
		this.connectSocket()
	}
	//断线重连
	reconnect(){
		return new Promise((result,reject)=>{
			if(this.isOnline){
				return reject(false)
			}
			
			if(this.isConnect && this.reconnectTime<=3){
				
				this.connectSocket()
				this.reconnectTime++
				result(true)
			}else{
				reject(false)
			}
		})
	}
	//震动
	messageNotice(){
		if(this.platform === 'android'){
			uni.vibrateShort()
		}else{
			uni.vibrateLong()
		}
		// 消息提示音
		
		if(this.bgAudioMannager.src){
			this.bgAudioMannager.play()
		}else{
			this.bgAudioMannager.src = '/static/notice3.mp3'; 
		}
	}
	//初始化会话列表
	initChatItem(message){
		//本地有没有这个会话列表
		let list = this.getChatList()
		
		//接收人/群id
		let id = 0
		let avatar = ''
		let name = ''
		let chat_type = ''
	
		id = message.id
		avatar = message.avatar
		name = message.name
		chat_type = message.chat_type
		//会话是否存在
		let index = list.findIndex(item => {
			return item.chat_type === message.chat_type && item.id === id
		})
		
		//最后一条消息
		
		let data = ''
		
		//会话不存在，创建
		if (index === -1) {
			//如果是我主动发的或者处于当前聊天
			let chatItem = {
				id, //聊天对象的id
				chat_type, //可能是群
				avatar, //群或人头像
				name, //群或人名称
				update_time: (new Date()).getTime(), //更新时间
				data, //会话内容
				type: 'system', //是文字还是图片
				noreadnum: 0, //未读数是多少
				istop: false,
				shownickname: false,
				nowarn: false, //消息免打扰
				strongwarn: false, //强提醒
				
			}
			//群聊
			if (message.chat_type === 'group') {
				
				chatItem = {
					...chatItem,
					// user_id: message.user_id, //管理员的id
					remark: "", //群公告
					invite_confirm: 1, //邀请确认
				}
			}
			list.unshift(chatItem)
		}
		//存储会话列表
		this.setChatList(list)
		
		//更新实时聊天的会话列表
		uni.$emit('onUpdateChatList', list)
		
		//没有则创建
		//更新会话列表
	}
	//处理moment动态
	handleMoment(msg){
		let notice = this.getNotice()
		
		
		switch(msg.type){
			case 'new': //朋友发布了朋友圈
			    //如果是我发的就不更新
				if(msg.user_id !== this.user.id){
					notice.avatar = msg.avatar
					notice.user_id = msg.user_id
					uni.showTabBarRedDot({
						index:2
					})
				}
				break;
			//点赞或评论
			default:
				if(msg.user_id !== this.user.id){
					notice.avatar = msg.avatar
					notice.user_id = msg.user_id
					notice.num+=1
				}
				
				if(notice.num>0){
					uni.setTabBarBadge({
						index:2,
						text:notice.num>99?'99+':notice.num.toString()
					})
				}else{
					uni.removeTabBarBadge({
						index:2
					})
				}
				break;
		}
		//实时推送
		uni.$emit('momentNotice',notice)
		//存储到本地
		$U.setStorage('moment_'+this.user.id,JSON.stringify(notice))
	}
	//获取本地存储中的朋友圈动态通知
	getNotice(){
		let notice = $U.getStorage('moment_'+this.user.id)
		return notice = notice ? JSON.parse(notice) : {
			avatar:"",
			user_id:0,
			num:0
		}
		
	}
	
	//读取朋友圈动态
	async readMoments(){
		let notice = {
			avatar:"",
			user_id:0,
			num:0
		}
		$U.setStorage('moment_'+this.user.id,JSON.stringify(notice))
		uni.removeTabBarBadge({
			index:2
		})
		uni.hideTabBarRedDot({
			index:2
		})
		//实时推送
		uni.$emit('momentNotice',notice)
	}
	//处理消息
	handleOnMessage(msg) {
		
		//添加消息历史记录
		if(msg.type==='onlinePosition' || msg.type === 'offlinePosition'){
			//全局通知
			return uni.$emit('onlinePosition', msg)
			
		}
		
		let {
			data,
			k
		} = this.addChatDetail(msg, false)
		//更新会话列表
		this.updateChatList(data, false)
		//更新实时聊天详情
		this.updateChatDetail(data, k, false)
		
		
	}
	//监听撤回消息处理
	handleOnRecall(message) {
		/* from_id:current_user_id,
        to_id,
        chat_type,
        id */
		
		let id = message.chat_type === 'group' ? message.to_id : message.from_id
		let key = `chatDetail_${this.user.id}_${message.chat_type}_${id}`
		//找到要撤回的消息详情
		//获取指定的聊天记录
		let detailList = this.getChatDetail(key)
		
		//找到要更新的消息详情
		let detailIndex = detailList.findIndex(v => v.id === message.id)
		//更改值
		detailList[detailIndex].isremove = 1
		//更新chat列表对话详情
		uni.$emit('updateChatDetail', {
			list:detailList,
			id:detailList[detailIndex].id,
			type:'recall'
		})
		//存储
		this.setStorage(key, detailList)
		//更新会话列表
		this.updateChatItem({
			id,
			chat_type:message.chat_type
		},(item)=>{
			
			item.data='对方撤回了一条消息'
			item.type='system'
			item.update_time = new Date().getTime()
			return item
		})

	}
	//创建聊天对象
	createChatObject(detail) {
		this.To = detail
	}
	//销毁聊天对象
	destoryChatObject() {
		this.To = false
	}
	//撤回消息
	recall({
		to_id,
		chat_type,
		id,
		from_id
	}) {
		return new Promise((result,reject)=>{
			$R.post('/chat/recall', {
				to_id,
				chat_type,
				id
			}).then(res => {
				
				let key = `chatDetail_${this.user.id}_${chat_type}_${to_id}`
				//获取指定的聊天记录
				let detailList = this.getChatDetail(key)
				//找到要更新的消息详情
				let detailIndex = detailList.findIndex(v => v.id === id)
				//更改值
				detailList[detailIndex].isremove = 1
				
				//存储
				this.setStorage(key, detailList)
				//更新chat列表对话详情
				result(detailList[detailIndex])
				//更新会话列表
				this.updateChatItem({
					id:to_id,
					chat_type
				},(item)=>{
			
					item.data='你撤回了一条消息'
					item.type='system'
					item.update_time = new Date().getTime()
					return item
				})
				
			}).catch(err => {
				reject(err)
			})
		})
	}
	
	//更新指定会话
	updateChatItem(chatItem,data=false) {
	
		//获取所有会话列表
		let list = this.getChatList()
		//找到当前会话
		let index = list.findIndex(item => item.id === chatItem.id && item.chat_type === chatItem.chat_type)

		if (index === -1) {
			return false
		}
	
		//更新数据
		if(typeof data === 'function'){
			list[index] = data(list[index])
			uni.$emit('onUpdateChatList', list)
		}else{
			list[index] = chatItem
		}
		
		//监听更新群状态
		uni.$emit('updateGroupState', list[index])
		let key = 'chatList_' + this.user.id
		this.setStorage(key, list)
	
	}
	//发送消息
	async send(message, onProgress = false) {
		return new Promise(async (result, reject) => {
			if (!this.checkOnline()) return reject('未上线')
			//添加消息详情历史记录
			let { k } = this.addChatDetail(message)
			//验证是否上线
			//上传文件
			//上传范围
			let isUpload = (message.type != 'text' && message.type != 'emoticon' && !message.data.startsWith('http') &&
				message.type != 'card'  && message.type != 'position')
			let uploadResult = ''
			if (isUpload) {
				uploadResult = await $R.upload('/upload', {
					filePath: message.data
				}, onProgress) 
				
				if(!uploadResult){
					message.sendStatus = 'fail'
					
					reject(err)
				}
			}
			
			let data = isUpload ? uploadResult : message.data
	
			
			//发送消息
			$R.post('/chat/send', {
				to_id: message.to_id || this.To.id,
				chat_type: message.chat_type || this.To.chat_type,
				type: message.type || this.To.type,
				data: data,
				options: JSON.stringify(message.options)
			}).then(res => {
				result(res)
				
				
				//发送成功的时间
				message.id = res.id
				message.sendStatus = 'success'
				if (message.type === 'video') {
					message.options = res.options
				}
				//更新会话列表
				this.updateChatList(message)
				//更新历史记录
				this.updateChatDetail(message, k)
		 
			}).catch(err => {
				message.sendStatus = 'fail'
				
				reject(err)
			})
		}) 
	}
	
	

	//清空聊天记录
	clearChatDetail(id, chat_type) {
		 // console.log(id,chat_type)
		let key = `chatDetail_${this.user.id}_${chat_type}_${id}`
		$U.removeStorage(key)
		//获取所有会话列表
		let list = this.getChatList()
		//找到当前会话
		let index = list.findIndex(item => item.id === id && item.chat_type === chat_type)
		if (index !== -1) {
			list[index].data = ''
			let key = 'chatList_' + this.user.id
			this.setStorage(key, list)
			return true

		}
		return false
	}

	//添加与别人的聊天记录
	addChatDetail(message, isSend = true) {

		//获取接收消息者的id,接收者可以是本人也可以是对方
		let id = message.chat_type === 'user' ? (isSend ? message.to_id : message.from_id) : message.to_id

		//key值:chatDetail_当前用户id_会话类型_人或群id
		let key = `chatDetail_${this.user.id}_${message.chat_type}_${id}`

		//获取指定的聊天记录
		let list = this.getChatDetail(key)
		//更新的头像
		// list.forEach(item=>{
		// 	if(isSend){
		// 		if(item.from_id===this.user.id){
		// 			return item.from_avatar = message.from_avatar
		// 		}
		// 	}
			
		// 	if(!isSend){
		// 		if(item.to_id === this.user.id){
		// 			item.from_avatar = message.from_avatar
		// 		}
		// 	}
		// })
		
		//标识
		message.k = 'k_' + list.length
		list.push(message)
		//存入本地
		this.setStorage(key, list)
		//返回
		return {
			data: message,
			k: message.k
		}
	}

	//获取聊天记录
	getChatDetail(key = false) {
		//获取当前聊天页面的聊天记录
		key = key ? key : `chatDetail_${this.user.id}_${this.To.chat_type}_${this.To.id}`
		
		return this.getStorage(key)
	}
	
	//获取聊天记录
	setChatDetail(list,key = false) {
		//获取当前聊天页面的聊天记录
		key = key ? key : `chatDetail_${this.user.id}_${this.To.chat_type}_${this.To.id}`
		return this.setStorage(key,JSON.stringify(list))
	}

	//判断是否上线
	checkOnline() {
		if (!this.isOnline) {
			//断线重连
			this.reconnectConfirm()
			return false
		}
		return true
	}
	
	
	//更新会话列表
	updateChatList(message, isSend = true) {
		
		//获取本地会话列表
		let list = this.getChatList()
		//是否处于当前聊天
		let isCurrentChat = false
		//接收人/群id
		let id = 0
		let avatar = ''
		let name = ''
		//判断私聊还是群聊
		if (message.chat_type === 'user') {
			//聊天对象存在的情况下，判断是否处于聊天中
			isCurrentChat = this.To ? this.To.id === message.from_id || this.To.id === message.to_id : false
			//拿到别人的id,avatar,name
			id = isSend ? message.to_id : message.from_id
			avatar = isSend ? message.to_avatar : message.from_avatar
			name = isSend ? message.to_name : message.from_name
		} else {
			//是否在当前会话
			isCurrentChat = this.To ? this.To.id === message.to_id : false
			//拿到群的id,avatar,name
			id = message.to_id
			avatar = message.to_avatar
			name = message.to_name
		}
		this.isCurrentChat = isCurrentChat
		
		//会话是否存在
		let index = list.findIndex(item => {
			return item.chat_type === message.chat_type && item.id === id
		})

		//最后一条消息

		let data = message.data && message.data.length > 18 ? message.data.slice(0, 18) + '...' : message.data
		data = this.formatChatItem(message, isSend)
		//未读数是否加一
		let noreadnum = isCurrentChat ? 0 : 1
		//会话不存在，创建
		if (index === -1) {
			//如果是我主动发的或者处于当前聊天
			let chatItem = {
				id, //聊天对象的id
				chat_type: message.chat_type, //可能是群
				avatar, //群或人头像
				name, //群或人名称
				update_time: (new Date()).getTime(), //更新时间
				data: data, //会话内容
				type: message.type, //是文字还是图片
				noreadnum: noreadnum, //未读数是多少
				istop: false,
				shownickname: false,
				nowarn: false, //消息免打扰
				strongwarn: false, //强提醒
				friendsInfo: message.friendsInfo
			}
			//群聊
			if (message.chat_type === 'group') {
				chatItem.name = message.to_name
				chatItem = {
					...chatItem,
					user_id: message.user_id, //管理员的id
					remark: "", //群公告
					invite_confirm: 1, //邀请确认
				}
			}
			list.unshift(chatItem)
		} else {
			 // console.log(message)
			//更新会话
			let item = list[index]
			// //更新该会话最后一条消息时间，内容，类型
			item.data = data
			item.name = name
			item.type = message.type
			//未读数更新
			item.noreadnum += noreadnum
			//置顶会话
			this.listToFirst(list, index)

		}
		//存储会话列表
		this.setChatList(list)
		//更新未读数
		this.updateBadge(list)
		//更新实时聊天的会话列表
		uni.$emit('onUpdateChatList', list)
		if(!isCurrentChat){
			this.messageNotice()
		}
		return list

	}
	//最后一条消息
	formatChatItem(message, isSend) {
		let data = message.data
		switch (message.type) {
			case 'emoticon':
				data = '[表情]'
				break;
			case 'image':
				data = '[图片]'
				break;
			case 'audio':
				data = '[语音]'
				break;
			case 'video':
				data = '[视频]'
				break;
			case 'card':
				data = '[名片]'
				break;
			case 'position':
				data = '[定位]'
				break;
			case 'onlinePosition':
				data = '[实时定位]'
				break;
		}

		data = isSend ? data : `${message.from_name}:${data}`
		return data
	}
	//存储会话列表
	setChatList(list) {
		let key = 'chatList_' + this.user.id
		this.setStorage(key, list)
	}
	//更新未读数
	updateBadge(list = false) {
		//获取所有会话列表
		list = list ? list : this.getChatList()
		//统计所有未读数
		let total = 0
		list.forEach(item => {
			total += item.noreadnum
		})

		//设置底部导航栏角标

		let count = total > 99 ? '99+' : total
		if (count > 0) {
			uni.setTabBarBadge({
				index: 0,
				text: count.toString()
			})


		} else {
			uni.removeTabBarBadge({
				index: 0
			})
		}
		uni.$emit('updateBadge', total)
		return total
	}
	//数组置顶
	listToFirst(arr, index) {
		if (index != 0) {
			arr.unshift(arr.splice(index, 1)[0])
		}
		return arr
	}
	//读取会话列表
	readChatItem(id, chat_type) {
		//获取所有会话列表
		let list = this.getChatList()
		//找到当前会话
		let index = list.findIndex(item => item.id === id && item.chat_type === chat_type)

		if (index !== -1) {
			list[index].noreadnum = 0
			//存储当前会话
			this.setChatList(list)
			//重新更新实时会话列表状态
			uni.$emit('onUpdateChatList', list)
			//更新角标和vuex角标数量
			this.updateBadge()
		}
	}
	//获取指定会话
	getChatListItem(id, chat_type) {
		//获取所有会话列表
		let list = this.getChatList()
		//找到当前会话
		let index = list.findIndex(item => item.id === id && item.chat_type === chat_type)

		if (index !== -1) {
			return list[index]
		}
		return false
	}
	//获取本地会话列表
	getChatList() {
		let key = 'chatList_' + this.user.id

		return this.getStorage(key)
	}
	
	//删除指定会话
	removeChatItem(id, chat_type) {
		//获取所有会话列表
		let list = this.getChatList()
		//找到当前会话
		let index = list.findIndex(item => item.id === id && item.chat_type === chat_type)

		if (index !== -1) {
			list.splice(index, 1)
			let key = 'chatList_' + this.user.id
			this.setStorage(key, list)
			//更新未读数
			this.updateBadge()
			return true

		}
		return false
	}
	//删除指定聊天记录
	deleteChatDetailItem(message,isSend=true){
		
		let id = message.chat_type==='user'?(isSend ? message.to_id : message.from_id):message.to_id
		//key值:chatDetail_当前用户id_会话类型_人或群id
		let key = `chatDetail_${this.user.id}_${message.chat_type}_${id}`
		
		//获取与某人的聊天记录
		let list = this.getChatDetail(key)
		//根据k查找对应聊天记录
		let index = list.findIndex(item => item.k === message.k || item.id===message.id)
		if (index === -1) {
			return
		}
		list.splice(index,1)
		
		this.setStorage(key, list)
		
		
		
	}
	//更新历史记录
	updateChatDetail(message, k, isSend = true) {
		
		//获取原来的历史记录
		//获取接收消息者的id,接收者可以是本人也可以是对方
		let id = message.chat_type === 'user' ? (isSend ? message.to_id : message.from_id) : message.to_id

		//key值:chatDetail_当前用户id_会话类型_人或群id
		let key = `chatDetail_${this.user.id}_${message.chat_type}_${id}`
		
		//获取与某人的聊天记录
		let list = this.getChatDetail(key)
		//根据k查找对应聊天记录
		let index = list.findIndex(item => item.k === k)
		
		if (index === -1) {
			return
		}
		list[index] = message
		
		let isCurrentChat = false
		
		if (message.chat_type === 'user') {
			//聊天对象存在的情况下，判断是否处于聊天中
			isCurrentChat = this.To ? this.To.id === message.from_id || this.To.id === message.to_id : false
			
		} else {
			//是否在当前会话
			isCurrentChat = this.To ? this.To.id === message.to_id : false
			
		}
		
		this.isCurrentChat = isCurrentChat
		
		//重新存储
		uni.$emit('updateChatDetail', {
			list,
			isSend
		})
		this.setStorage(key, list)
	}
	getUser(){
		let user = $U.getStorage('user')
		user = user ? JSON.parse(user) : {
			id: 0
		}
		return user
	}
	//获取存储
	getStorage(key) {
		let list = $U.getStorage(key)

		return list ? JSON.parse(list) : []
	}

	//存入本地
	setStorage(key, list) {

		$U.setStorage(key, JSON.stringify(list))
	}

	//格式化发送信息数据
	fromatSendData(params) {
		let user = this.getUser()
		return {
			id: 0, //用于撤回指定消息
			from_avatar: user.avatar,
			from_name: user.nickname || user.username,
			from_id: this.user.id,
			to_id:params.to_id || this.To.id,
			to_name: params.to_name || this.To.name,
			to_avatar:params.to_avatar || this.To.avatar,
			chat_type:params.chat_type || this.To.chat_type, //接收类型，群组还是个人
			type: params.type, //消息类型 video text audio image
			data: params.data, //消息内容
			options: params.options ? params.options : {}, // 其它参数
			create_time: (new Date()).getTime(), //格式化时的时间
			isremove: 0, //是否撤回
			sendStatus: params.sendStatus ? params.sendStatus : "pending" //发送状态 success 发送成功,fail 失败 ,pending 发送中
		}
	}

}

export default chat
